package nettyTest.netty4test1.byteBuf;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.UnpooledByteBufAllocator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class ByteBufTest {

    private static final Logger logger = LogManager.getLogger(ByteBufTest.class);

    public static void main(String[] args) {

        UnpooledByteBufAllocator aDefault = UnpooledByteBufAllocator.DEFAULT;
        ByteBuf byteBuf = aDefault.heapBuffer();
        byteBuf.writeShort(123);
        logger.info(byteBuf.refCnt());

        try {
            byteBuf.retain();
            logger.info(byteBuf.refCnt());
            Thread thread1 = new Thread(() -> {
                try {
                    byte[] bytes = new byte[byteBuf.readableBytes()];
                    byteBuf.readBytes(bytes);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    byteBuf.release();
                    logger.info(byteBuf.refCnt());
                }
            });
            thread1.start();

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            byteBuf.retain();
            logger.info(byteBuf.refCnt());
            System.gc();
            byteBuf.resetReaderIndex();
            Thread thread2 = new Thread(() -> {
                try {
                    byte[] bytes = new byte[byteBuf.readableBytes()];
                    byteBuf.readBytes(bytes);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    byteBuf.release();
                    logger.info(byteBuf.refCnt());
                }
            });
            thread2.start();

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            logger.info(byteBuf.refCnt());
            byteBuf.release();
            logger.info(byteBuf.refCnt());
        }
    }


    /**
     * 对于内存泄漏的检测 https://blog.csdn.net/shuaixingrumo/article/details/124112314
     * 参数 -Dio.netty.leakDetection.level=advanced
     */
    @Test
    public void retainTest() throws InterruptedException {
        PooledByteBufAllocator allocator = new PooledByteBufAllocator(true);
        IntStream.range(0, 128).forEach(i -> {
            ByteBuf bf = allocator.directBuffer(100);
//            bf.release();
//            bf = null;
            System.gc();
        });
        TimeUnit.SECONDS.sleep(11);
    }

    @Test
    public void writeOutIndex(){
        ByteBuf byteBuf = PooledByteBufAllocator.DEFAULT.directBuffer(64);
//        try {
//            byteBuf.writerIndex(65);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        System.out.println(byteBuf.capacity());
        byteBuf.writeLong(44444444444444444l);
        byteBuf.writeLong(44444444444444444l);
        byteBuf.writeLong(44444444444444444l);
        byteBuf.writeLong(44444444444444444l);
        byteBuf.writeLong(44444444444444444l);
        byteBuf.writeLong(44444444444444444l);
        byteBuf.writeLong(44444444444444444l);
        byteBuf.writeLong(44444444444444444l);
        byteBuf.writeLong(44444444444444444l);
        System.out.println(byteBuf.writerIndex());
        System.out.println(byteBuf.capacity());


    }
}
